package org.liquidByte.trafficMustang.androidApp.overlays;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import android.app.Activity;
import android.graphics.Bitmap;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;

public class TrackingOverlay extends SingleMarkerOverlay {
	
	private MapView mapView;
	private final Tracker tracker;
	private ScheduledExecutorService pool;
	private ScheduledFuture<?> executingFuture;
	private long initialDelay;
	private long delay;
	private TimeUnit timeUnit;
	private boolean centerOnNewMark;
	private Activity activity;
	
	public TrackingOverlay(Activity activity, MapView mapView, Bitmap pushpin, Tracker tracker, long initialDelay, long delay, TimeUnit timeUnit, boolean centerOnNewMark) {
		super(pushpin);
		if (mapView == null) {
			throw new IllegalArgumentException("mapView is null");
		}
		if (tracker == null) {
			throw new IllegalArgumentException("tracker is null");
		}
		if (activity == null) {
			throw new IllegalArgumentException("activity is null");
		}
		this.mapView = mapView;
		this.tracker = tracker;
		this.initialDelay = initialDelay;
		this.delay = delay;
		this.timeUnit = timeUnit;
		this.centerOnNewMark = centerOnNewMark;
		this.activity = activity;
	}
	
	protected ScheduledExecutorService getPool() {
		if (this.pool == null) {
			this.pool = Executors.newScheduledThreadPool(1);
		}
		return pool;
	}
	protected void setPool(ScheduledExecutorService pool) {
		if (!(pool == null && this.pool == null ||
			  pool != null && this.pool != null && this.pool.equals(pool))) {
			if (this.pool != null) {
				this.setExecutingFuture(null);
				this.pool.shutdown();
			}
			this.pool = pool;
		}
	}
	protected ScheduledFuture<?> getExecutingFuture() {
		return this.executingFuture;
	}	
	protected void setExecutingFuture(ScheduledFuture<?> future) {
		if (!(this.executingFuture == null && future == null ||
			  this.executingFuture != null && future != null && this.executingFuture.equals(future))) {
			if (this.executingFuture != null) {
				this.executingFuture.cancel(false);
			}
			this.executingFuture = future;
		}
		this.executingFuture = future;
	}
	protected MapView getMapView() {
		return mapView;
	}
	@Override
	protected synchronized void setMark(GeoPoint mark) {
		final GeoPoint passMark = mark;
		if (!(mark == null && this.getMark() == null ||
			  mark != null && this.getMark() != null && this.getMark().equals(mark))) {
			super.setMark(mark);
			this.activity.runOnUiThread(new Runnable() {
				
				@Override
				public void run() {
					TrackingOverlay overlay = TrackingOverlay.this;
					overlay.mapView.invalidate();
					if (overlay.centerOnNewMark) {
						overlay.mapView.getController().animateTo(passMark);	
					}
				}
			});
		}
	}
	public boolean isStarted() {
		return this.executingFuture != null;
	}
	
	public void start() {
		if (!this.isStarted()) {
			this.setExecutingFuture(this.getPool().scheduleWithFixedDelay(new Runnable() {
				
				@Override
				public void run() {
					TrackingOverlay overlay = TrackingOverlay.this;
					overlay.setMark(overlay.tracker.getLocation());
				}
			}, this.initialDelay, this.delay, this.timeUnit));
		}
	}
	
	public void stop() {
		if (this.isStarted()) {
			this.setPool(null);
		}
	}

	public interface Tracker {
		GeoPoint getLocation();
	}
}
